package com.glodon.paas.document.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.glodon.paas.account.api.bean.Communicate;
import com.glodon.paas.account.api.bean.Member;
import com.glodon.paas.account.api.bean.Org;
import com.glodon.paas.account.api.bean.User;
import com.glodon.paas.consts.StringConst;
import com.glodon.paas.document.api.bean.MemberView;
import com.glodon.paas.document.api.bean.Project;
import com.glodon.paas.document.api.bean.ProjectMember;
import com.glodon.paas.document.api.bean.ProjectMemberAttendees;
import com.glodon.paas.document.api.bean.ProjectResource;
import com.glodon.paas.document.api.bean.ProjectRole;
import com.glodon.paas.document.api.bean.StringUtil;
import com.glodon.paas.document.biz.FileBiz;
import com.glodon.paas.document.biz.ProjectBiz;
import com.glodon.paas.document.biz.ProjectResourceBiz;
import com.glodon.paas.document.constant.DocumentConstant;
import com.glodon.paas.document.dao.domain.FileInfoEntity;
import com.glodon.paas.document.dao.domain.InvitationEntity;
import com.glodon.paas.document.dao.domain.ProjectInfoEntity;
import com.glodon.paas.document.dao.domain.ProjectMemberAttendeesEntity;
import com.glodon.paas.document.dao.domain.ProjectMemberEntity;
import com.glodon.paas.document.dao.domain.ProjectResourceEntity;
import com.glodon.paas.document.dao.domain.ProjectRoleEntity;
import com.glodon.paas.document.service.ProjectService;
import com.glodon.paas.document.service.util.DocumentPrivilege;
import com.glodon.paas.document.service.util.MailPropertiesUtil;
import com.glodon.paas.document.service.util.RoleMessages;
import com.glodon.paas.document.service.util.WebService;
import com.glodon.paas.exception.PaasServerExceptionFactory;
import com.glodon.paas.exception.i18n.ErrorCode;
import com.glodon.paas.mail.MailClientHttpImpl;
import com.glodon.paas.mail.MailMessageParam;
import com.glodon.paas.util.DateUtil;
import com.glodon.paas.util.TokenGenerator;
import com.glodon.paas.util.UUIDUtil;

@Service("projectService")
public class ProjectServiceImpl implements ProjectService {

    @Autowired
    private ProjectBiz         projectBiz;
    @Autowired
    private ProjectResourceBiz resourceBiz;
    @Autowired
    private FileBiz            fileBiz;
    @Autowired
    private MailClientHttpImpl mailClient;
    @Autowired
    private DocumentPrivilege  privilege;
    @Autowired
    private WebService webService;

    @Override
    public Project createProject(String userId, String email, String name, String description) {
        //TODO 需要检查项目创建权限，目前不检查
        if (StringUtils.isBlank(name)) {
            throw PaasServerExceptionFactory.validateException("Project name should not be empty!",
                                                               new Exception("Project name is empty!")).setErrorCode(ErrorCode.EMPTY_PROJECT_NAME);
        }
        ProjectInfoEntity pe = projectBiz.getProjectByName(userId, name);
        if (pe != null) {
            throw PaasServerExceptionFactory.validateException("There is a project with the same name!",
                                                               new Exception("Project name is duplicate!")).setErrorCode(ErrorCode.DUPLICATE_PROJECT);
        }
        Date now = DateUtil.getNow();
        
        // project
        ProjectInfoEntity project = new ProjectInfoEntity();
        project.setId(UUIDUtil.getUUIDStr());
        project.setOwnerId(userId);
        project.setIsDelete(0);
        project.setName(name);
        project.setDescription(description);

        // root folder
        FileInfoEntity folder = new FileInfoEntity();
        folder.setId(UUIDUtil.getUUIDStr());
        folder.setName(name);
        folder.setExtension("");
        folder.setType(DocumentConstant.FILE_TYPE_FOLDER);
        folder.setCreateTime(now);
        folder.setUpdateTime(now);
        folder.setOwnerId(project.getId());
        folder.setParentId(project.getId());
        folder.setDeletedStatus(DocumentConstant.FILE_STATUS_NORMAL);
        folder.setCreator(userId);
        folder.setUpdator(userId);
        project.setFolderId(folder.getId());
        
        // 管理员 角色
        ProjectRoleEntity ownerRole = new ProjectRoleEntity();
        ownerRole.setId(UUIDUtil.getUUIDStr());
        ownerRole.setRoleName(RoleMessages.getString("ProjectServiceImpl.Creator"));
        ownerRole.setProjectId(project.getId());
        ownerRole.setCreator(userId);
        ownerRole.setIsEditable(0);
        ownerRole.setIsVisible(1);
        ownerRole.setUpdator(userId);
        ownerRole.setIsDefault(0);
        ownerRole.setIsDeleted(0);
        ownerRole.setCreateTime(now);
        ownerRole.setUpdateTime(now);
        
        // 未分配 角色
        ProjectRoleEntity defaultRole = new ProjectRoleEntity();
        defaultRole.setId(UUIDUtil.getUUIDStr());
        defaultRole.setRoleName(RoleMessages.getString("ProjectServiceImpl.Undispatched"));
        defaultRole.setProjectId(project.getId());
        defaultRole.setIsDefault(1);
        defaultRole.setIsEditable(0);
        defaultRole.setIsVisible(1);
        defaultRole.setCreator(userId);
        defaultRole.setUpdator(userId);
        defaultRole.setIsDeleted(0);
        defaultRole.setCreateTime(now);
        defaultRole.setUpdateTime(now);
        
        // 添加 默认成员
        ProjectMemberEntity member = new ProjectMemberEntity();
        member.setId(UUIDUtil.getUUIDStr());
        member.setProjectId(project.getId());
        member.setRoleId(ownerRole.getId());
        member.setStatus(1);
        member.setMemberType(0);
        member.setUserId(userId);
        member.setCreateTime(now);
        member.setUpdateTime(now);
        member.setEditable(1);
        //Add attendees
        ProjectMemberAttendeesEntity attendee = new ProjectMemberAttendeesEntity();
        attendee.setId(UUIDUtil.getUUIDStr());
        attendee.setMemberId(member.getId());
        attendee.setStatus(1);
        attendee.setEditable(1);
        attendee.setUserId(userId);
        attendee.setCreateTime(now);
        attendee.setUpdateTime(now);
        attendee.setCreator(userId);
        attendee.setUpdator(userId);
        // 管理员角色默认权限，读，写，删除，进入
        ProjectResourceEntity ownerRoleResource = new ProjectResourceEntity();
        ownerRoleResource.setId(UUIDUtil.getUUIDStr());
        ownerRoleResource.setFileId(folder.getId());
        ownerRoleResource.setPrivileges(DocumentConstant.FILE_READ+StringConst.SEPARATOR_COMMA+
                               DocumentConstant.FILE_WRITE+StringConst.SEPARATOR_COMMA+
                               DocumentConstant.FILE_DELETE+StringConst.SEPARATOR_COMMA+
                               DocumentConstant.FILE_ENTER);
        ownerRoleResource.setRoleId(ownerRole.getId());
        ownerRoleResource.setUpdateTime(now);
        ownerRoleResource.setUpdatorId(userId);
        
        // 未分配人员默认权限， 进入
        ProjectResourceEntity defaultRoleResource = new ProjectResourceEntity();
        defaultRoleResource.setId(UUIDUtil.getUUIDStr());
        defaultRoleResource.setFileId(folder.getId());
        defaultRoleResource.setPrivileges(DocumentConstant.FILE_ENTER);
        defaultRoleResource.setRoleId(defaultRole.getId());
        defaultRoleResource.setUpdateTime(now);
        defaultRoleResource.setUpdatorId(userId);
        
        
        String id = projectBiz.createProject(project, folder, ownerRole, defaultRole, member,attendee, ownerRoleResource, defaultRoleResource);
        // add member in account
        webService.addProjectRole(userId,userId, member.getProjectId(), member.getRoleId(),null);
        return ProjectInfoEntity.getDto(project);
//        projectDto.setFiles(new ArrayList<File>());
//        projectDto.getFiles().add(FileInfoEntity.getDto(folder, false));
//        return projectDto;
    }
    
    @Override
    public boolean deleteProject(String userId, String projectId) {
        // TODO 需要检查项目删除权限, 目前检查项目跟目录的删除权限，只有管理员有
        ProjectInfoEntity entity = projectBiz.getProjectById(projectId);
        if (entity != null) {
            privilege.checkRemovePrivilege(userId, entity.getFolderId(), false, false);
            fileBiz.deleteFile(entity.getFolderId());
            return projectBiz.deleteProject(projectId);
        }

        return false;

    }

    @Override
    public Project updateProject(String userId, Project project) {
        if (StringUtils.isBlank(project.getName())) {
            throw PaasServerExceptionFactory.validateException("Project name should not be empty!",
                                                               new Exception("Project name is empty!")).setErrorCode(ErrorCode.EMPTY_PROJECT_NAME);
        }
        ProjectInfoEntity dbProject = projectBiz.getProjectById(project.getId());
        if (dbProject == null) {
            throw PaasServerExceptionFactory.notFoundException("can not find project["+project.getId()+"]", null);
        }
        // TODO 需要检查项目更新权限，目前检查根目录的写权限，只有管理员有
        privilege.checkWritePrivilege(userId, dbProject.getFolderId(), false, false);
        dbProject.setName(project.getName());
        dbProject.setDescription(project.getDescription());
        dbProject.setUpdateTime(DateUtil.getNow());
        projectBiz.updateProject(dbProject);
        fileBiz.updateFileName(dbProject.getFolderId(), project.getName(), userId);
        return ProjectInfoEntity.getDto(dbProject);
    }

    @Override
    public ProjectRole createRole(String userId, String projectId, String roleName) {
        ProjectInfoEntity project = projectBiz.getProjectById(projectId);
        if (project == null) {
            throw PaasServerExceptionFactory.notFoundException("can not find project["+projectId+"]", null);
        }
        Date now = DateUtil.getNow();
        // TODO 需要检查角色创建全新，目前检查项目根目录的写权限，只有管理员有
        privilege.checkWritePrivilege(userId, project.getFolderId(), false, false);
        ProjectRoleEntity role = new ProjectRoleEntity();
        role.setCreator(userId);
        role.setId(UUIDUtil.getUUIDStr());
        role.setProjectId(projectId);
        role.setIsDefault(0);
        role.setIsVisible(1);
        role.setIsEditable(1);
        role.setRoleName(roleName);
        role.setCreateTime(now);
        role.setUpdateTime(now);
        // check the same name role
        boolean result = projectBiz.checkSameRole(role);
        if (result) {
            throw PaasServerExceptionFactory.validateException("There is a role with the same name!",
                                                               new Exception("Role name is duplicate!")).setErrorCode(ErrorCode.DUPLICATE_ROLE);
        }
        // 新角色 根目录 有进入权限
        ProjectResourceEntity resource = new ProjectResourceEntity();
        resource.setId(UUIDUtil.getUUIDStr());
        resource.setFileId(project.getFolderId());
        resource.setPrivileges(DocumentConstant.FILE_ENTER);
        resource.setRoleId(role.getId());
        resource.setUpdateTime(DateUtil.getNow());
        resource.setUpdatorId(userId);
        
        projectBiz.createRole(role, resource);
        
        return ProjectRoleEntity.getDto(role);
    }

    @Override
    public List<ProjectRole> getProjectRoles(String userId, String projectId) {
        ProjectInfoEntity project = projectBiz.getProjectById(projectId);
        if(project == null){
            throw PaasServerExceptionFactory.notFoundException("can not find project["+projectId+"]", null);
        }
        // TODO 需要检查角色更新权限，目前检查项目根目录的读权限，只有管理员有
        privilege.checkReadPrivilege(userId, project.getFolderId(), false, false);
        return ProjectRoleEntity.getDtos(projectBiz.listRoles(projectId), true);
    }

    @Override
    public ProjectRole updateRole(String userId, String roleId, String name) {
        if(StringUtils.isBlank(roleId) || StringUtils.isBlank(name)){
            throw PaasServerExceptionFactory.validateException("roleId or role name is empty.", null);
        }
        ProjectRoleEntity role = projectBiz.getRole(roleId);
        if(role == null){
            throw PaasServerExceptionFactory.notFoundException("can not find Role["+roleId+"]", null);
        }
        ProjectInfoEntity project = projectBiz.getProjectById(role.getProjectId());
        if (project == null) {
            throw PaasServerExceptionFactory.notFoundException("can not find project["+role.getProjectId()+"]", null);
        }
        // TODO 需要检查角色更新权限，目前检查项目根目录的写权限
        privilege.checkWritePrivilege(userId, project.getFolderId(), false, false);
        if(role.isEditable()){
            return ProjectRoleEntity.getDto(projectBiz.updateRole(userId, roleId, name));
        }
        else{
            throw PaasServerExceptionFactory.systemException("system defined Role, can not update.", null);
        }
    }

    @Override
    public void deleteRole(String userId, String roleId) {
        ProjectRoleEntity role = projectBiz.getRole(roleId);
        if(role == null){
            throw PaasServerExceptionFactory.notFoundException("can not find Role["+roleId+"]", null);
        }
        ProjectInfoEntity project = projectBiz.getProjectById(role.getProjectId());
        if (project == null) {
            throw PaasServerExceptionFactory.notFoundException("can not find project["+role.getProjectId()+"]", null);
        }
        // TODO 需要检查角色删除权限，目前检查项目根目录的删除权限
        privilege.checkRemovePrivilege(userId, project.getFolderId(), false, false);
        if(role.isEditable()){
            projectBiz.deleteRole(roleId);
            // Get default role id
            ProjectRoleEntity defaultRole = projectBiz.getDefaultRole(role.getProjectId());
            webService.updateProjectRole(userId, role.getProjectId(), roleId, defaultRole.getId());
        }
        else{
            throw PaasServerExceptionFactory.systemException("system defined Role, can not delete.", null);
        }
    }

    @Override
    public String insertMember(ProjectMemberEntity entity) {
        return projectBiz.insertMember(entity);
    }

    @Override
    public boolean updateMemberStatus(String memberId, int status) {
        return projectBiz.updateMemberStatus(memberId, status);
    }

    @Override
    public Project getProject(String userId, String projectId) {
        ProjectInfoEntity dbProject = projectBiz.getProjectById(projectId);
        if (dbProject == null) {
            throw PaasServerExceptionFactory.notFoundException("can not find project["+projectId+"]", null);
        }
        // TODO 需要检查项目读权限，目前检查项目根目录的任意权限
        privilege.checkAnyPrivilege(userId, dbProject.getFolderId(), false, false);
        return ProjectInfoEntity.getDto(dbProject);
    }

    @Override
    public boolean insertInvitation(InvitationEntity entity) {
        return projectBiz.insertInvitation(entity);
    }

    @Override
    public boolean confirmInvitation(String userId, String token) {
        return projectBiz.confirmInvitation(userId, token);
    }

    @Override
    public List<Project> getProjectsByIds(List<String> ids) {
        return ProjectInfoEntity.getDtos(projectBiz.getProjectByIds(ids));
    }

    @Override
    public List<ProjectMember> getMembers(String projectId, String roleId) {
        return ProjectMemberEntity.getDtos(projectBiz.getMembers(projectId, roleId));
    }

    @Override
    public ProjectMember getConfirmedMember(String userId, String token) {
        return ProjectMemberEntity.getDto(projectBiz.getConfirmedMember(userId, token));
    }

    @Override
    public boolean removeMember(String memberId,boolean deleteMember) {
        return projectBiz.removeMember(memberId,deleteMember);
    }

    @Override
    public ProjectMember getMemberById(String memberId) {
        return ProjectMemberEntity.getDto(projectBiz.getMember(memberId));
    }

    @Override
    public ProjectRole getDefaultRole(String projectId) {
        return ProjectRoleEntity.getDto(projectBiz.getDefaultRole(projectId));
    }

    @Override
    public boolean updateRoleOfMember(String memberId, String projectId, String oldRoleId, String newRoleId) {
        return projectBiz.updateRoleOfMember(memberId, projectId, oldRoleId, newRoleId);
    }

    @Override
    public List<MemberView> inviteMembers(MemberView member, User owner, String basePath) {
        String roleId = member.getRoleId();
        String projectId = member.getProjectId();
        // if(member.getMembers()!=null&&!member.getMembers().isEmpty()){
        //
        // roleId = member.getMembers().get(0).getRoleId();
        // projectId = member.getMembers().get(0).getProjectId();
        // }

        if (StringUtils.isEmpty(roleId)) {
            ProjectRole role = getDefaultRole(projectId);
            roleId = role.getId();
        }

        // step1: insert into member table
        Map<String, ProjectMemberEntity> statusMap = new HashMap<String, ProjectMemberEntity>();
        // Get project information
        ProjectInfoEntity project = projectBiz.getProjectById(projectId);
        if (project == null) {
            throw PaasServerExceptionFactory.validateException("Project is not exist!",
                                                               new Exception("Project is not exist!"));
        }
        // TODO here is for multi inviting in future
        List<MemberView> members = new ArrayList<MemberView>();
        members.add(member);
        // if is group,get org members
        List<Org> orgList = new ArrayList<Org>();

        inviteMember(member,owner,project,basePath,orgList,statusMap);

        // Get user information
        //get members
        List<MemberView> result = new ArrayList<MemberView>();
        for (MemberView memberView : members) {
            if (!memberView.isOrg()) {
                String userId="";
                if(!StringUtil.isBlank(memberView.getOrgId())){
                    userId =memberView.getUserId();
                }else{
                    userId = memberView.getAccount();
                }
                User user = webService.getUser(userId);
                if(user==null){
                    user = webService.getInactiveUser(memberView.getAccount());
                }
                ProjectMemberEntity pm = statusMap.get(user.getId());
                memberView.setId(pm.getId());
                memberView.setUserId(pm.getUserId());
                memberView.setStatus(pm.getStatus());
                memberView.setMemberCount(0);
                memberView.setName(memberView.getAccount());
                if(user!=null){
                    memberView.setName(user.getDisplayName());
                }
                result.add(memberView);
            }
        }
        if (!orgList.isEmpty()) {
            List<MemberView> orgMembers = new ArrayList<MemberView>();
            for(Org org: orgList){
                //Get org full path
                Org fullOrg= webService.getOrgPath(org.getId(), owner.getId());
                this.convertOrgWithNameNode(fullOrg, org, statusMap,orgMembers);
            }
            setDetailForMemberView(orgMembers,statusMap,projectId,roleId);
            result.addAll(orgMembers);
        }
        return result;
    }
    private void inviteMember(MemberView member,User owner,ProjectInfoEntity project,String basePath,List<Org> orgList, Map<String, ProjectMemberEntity> statusMap){
        if(member.isOrg()){
            // insert into member database
            ProjectMemberEntity entity = new ProjectMemberEntity();
            entity.setCreateTime(DateUtil.getNow());
            entity.setId(UUIDUtil.getUUIDStr());
            entity.setProjectId(member.getProjectId());
            entity.setRoleId(member.getRoleId());
            entity.setStatus(1);
            entity.setIsOrg(1);
            entity.setMemberId(member.getUserId());
            entity.setUpdateTime(entity.getCreateTime());
            ProjectMemberEntity pm=projectBiz.getMember(member.getProjectId(), member.getRoleId(), entity.getMemberId(),null);
            if(pm!=null){
                throw PaasServerExceptionFactory.validateException("Member is already exist!",
                                                                   new Exception("Member is already exist!"));
            }
            insertMember(entity);
            //Get org members
            Org org = webService.getOrgById(member.getUserId(), owner.getId(),true);
            orgList.add(org);
            List<Member> memList = new ArrayList<Member>();
            this.getOrgMember(org, memList);
            if(!memList.isEmpty()){
                for (Member mem : memList) {
                    ProjectMemberAttendeesEntity attendees = new ProjectMemberAttendeesEntity();
                    attendees.setId(UUIDUtil.getUUIDStr());
                    attendees.setMemberId(entity.getId());
                    attendees.setStatus(0);
                    attendees.setUserId(mem.getUserId());
                    attendees.setCreator(owner.getId());
                    attendees.setUpdator(owner.getId());
                    attendees.setCreateTime(entity.getCreateTime());
                    attendees.setUpdateTime(entity.getCreateTime());
                    Map<String, Object> param = new HashMap<String, Object>();
                    param.put("owner", owner.getDisplayName());
                    param.put("projectName", project.getName());
                    String token = TokenGenerator.generate(mem.getEmail() + member.getRoleId() + member.getProjectId() + DateUtil.getNow());
                    String queryString = "?userId=" + attendees.getUserId() + "&token=" + token;
                    param.put("link", basePath+"/project/member/acception"+ queryString);
                    // Step2: send invitation mail
                    boolean mailResult = sendMail(mem.getEmail(), param,
                                                  MailPropertiesUtil.getString("project.mail.inviteMember.title"),
                                                  MailPropertiesUtil.getString("project.mail.inviteMember.template"));
                 // Step3: Insert invite history
                    InvitationEntity invitation = new InvitationEntity();

                    invitation.setId(UUIDUtil.getUUIDStr());
                    invitation.setAccount(attendees.getUserId());
                    invitation.setToken(token);
                    invitation.setStatus(0);
                    invitation.setMemberId(entity.getId());
                    invitation.setCreateTime(DateUtil.getNow());
                    invitation.setUpdateTime(invitation.getCreateTime());
                    insertInvitation(invitation);
                    //set invitation id
                    attendees.setInvitationId(invitation.getId());
                    projectBiz.insertAttendees(attendees);
                    if (!mailResult) {
                        entity.setStatus(-1);
                    }
                    //remember status of attendee
                    ProjectMemberEntity attendeeEntity = new ProjectMemberEntity();
                    attendeeEntity.setId(attendeeEntity.getId());
                    attendeeEntity.setMemberId(attendees.getUserId());
                    attendeeEntity.setStatus(attendees.getStatus());
                    statusMap.put(attendees.getUserId(), attendeeEntity);
                }
            }
        
        }else{
            //begin check if email/mobilephone is registered.
            User user = null;
            String userId="";
            //define if the user is in org
            boolean isInOrg = false;
            //if the member is new in Org
            String memberId ="";
            //define the status of user
            boolean isInActiveUser=false;
            if(!StringUtil.isBlank(member.getOrgId())){
                memberId = member.getOrgId();
                isInOrg = true;
                user=webService.getUser(member.getUserId());
                if(user==null){
                    user = webService.getInactiveUser(member.getAccount());
                }
            }else{
                user=webService.getUser(member.getAccount());
                if(user==null){
                    user = webService.getInactiveUser(member.getAccount());
                    if(user==null){
                        user= webService.createInactiveUser(member.getAccount());
                    }
                    isInActiveUser=true;
                }
                memberId = user.getId();
            }
           
            //TODO check member: if the user is already invited ,throw exception
            ProjectMemberEntity pm=projectBiz.getMember(member.getProjectId(), member.getRoleId(), memberId,null);
            if(pm!=null&&pm.getIsOrg()!=1){
                throw PaasServerExceptionFactory.validateException("Member is already exist!",
                                                                   new Exception("Member is already exist!"));
            }
            String attendeeMemberId ="";
            userId=user.getId();
            if(!isInOrg){
                
                // insert into member database
                ProjectMemberEntity entity = new ProjectMemberEntity();
                entity.setCreateTime(DateUtil.getNow());
                entity.setId(UUIDUtil.getUUIDStr());
                entity.setProjectId(member.getProjectId());
                entity.setRoleId(member.getRoleId());
                entity.setStatus(0);
                entity.setIsOrg(0);
                //end
                entity.setMemberId(user.getId());
                entity.setUpdateTime(entity.getCreateTime());
                insertMember(entity);
                statusMap.put(entity.getMemberId(), entity);
                attendeeMemberId = entity.getId();
            }else{
                
                attendeeMemberId = pm.getId();
                statusMap.put(userId, pm);
            }
           
            ProjectMemberAttendeesEntity attendees = new ProjectMemberAttendeesEntity();
            attendees.setId(UUIDUtil.getUUIDStr());
            attendees.setMemberId(attendeeMemberId);
            attendees.setStatus(0);
            attendees.setUserId(userId);
            attendees.setCreator(owner.getId());
            attendees.setUpdator(owner.getId());
            attendees.setCreateTime(DateUtil.getNow());
            attendees.setUpdateTime(DateUtil.getNow());
            projectBiz.insertAttendees(attendees);
            Map<String, Object> param = new HashMap<String, Object>();
            param.put("owner", owner.getDisplayName());
            param.put("projectName", project.getName());
            String token = TokenGenerator.generate(user.getEmail() + member.getRoleId() + member.getProjectId() + DateUtil.getNow());
            String queryString = "?userId=" + userId + "&token=" + token;
            param.put("link", basePath +"/project/member/acception"+ queryString);
            // Step2: send invitation mail
            if(!isInActiveUser){
                sendMail(user.getEmail(), param,
                         MailPropertiesUtil.getString("project.mail.inviteMember.title"),
                         MailPropertiesUtil.getString("project.mail.inviteMember.template"));
            }else{
                param.put("activeLink", basePath +"/index?userId=" + userId+"&email="+user.getEmail());
                sendMail(user.getEmail(), param,
                         MailPropertiesUtil.getString("project.mail.inviteMember.title"),
                         MailPropertiesUtil.getString("project.mail.inviteMember.Activetemplate"));
            }
           
            // Step3: Insert invite history
            InvitationEntity invitation = new InvitationEntity();

            invitation.setId(UUIDUtil.getUUIDStr());
            invitation.setAccount(userId);
            invitation.setToken(token);
            invitation.setStatus(0);
            invitation.setMemberId(attendeeMemberId);
            invitation.setCreateTime(DateUtil.getNow());
            invitation.setUpdateTime(invitation.getCreateTime());
            insertInvitation(invitation);
        }
    }
    private void setDetailForMemberView(List<MemberView> orgMembers,Map<String, ProjectMemberEntity> statusMap,String projectId,String roleId){
        for (MemberView mem : orgMembers) {
            if(mem.isOrg()){
                mem.setProjectId(projectId);
                mem.setRoleId(roleId);
                mem.setStatus(0);
                mem.setUserId(mem.getId());
                mem.setEditable(true);
            }else{
                ProjectMemberEntity pm = statusMap.get(mem.getUserId());
                mem.setId(pm.getId());
                User user = webService.getUser(pm.getMemberId());
                if(user!=null){
                    mem.setName(user.getDisplayName());
                }else{
                    mem.setName(mem.getAccount());
                }
                mem.setProjectId(projectId);
                mem.setRoleId(roleId);
                mem.setStatus(pm.getStatus());
                mem.setUserId(pm.getMemberId());
                mem.setEditable(pm.getEditable()!=1);
            }
            if(mem.getMemberViews()!=null&&!mem.getMemberViews().isEmpty()){
                setDetailForMemberView(mem.getMemberViews(),statusMap,projectId,roleId);
            }
            
        }
    }
    /**
     * Send email when invite a member into project
     * 
     * @param sendTo
     * @param title
     * @param template
     * @return
     */
    private boolean sendMail(String sendTo, Map<String, Object> param, String title, String template) {
        MailMessageParam mailContent = new MailMessageParam();
        mailContent.setTo(sendTo.split(";"));
        mailContent.setSubject(title);
        mailContent.setTemplateLocation(template);
        mailContent.setTemplateParam(param);
        int result = mailClient.sendMail(mailContent, false);
        return result == 200;
    }

    @Override
    public boolean reInvite(ProjectMember member, User owner, String basePath) {
        //TODO get project member object by :project id, role id, account id
        
        ProjectMemberEntity entity =projectBiz.getMember(member.getProjectId(), member.getRoleId(),member.getUserId(),null);
        member =ProjectMemberEntity.getDto(entity);
        // step1: update status in member table
        updateMemberStatus(member.getId(), 0);
        String projectId = member.getProjectId();
        ProjectInfoEntity project = projectBiz.getProjectById(projectId);
        if (project == null) {
            throw PaasServerExceptionFactory.validateException("Project is not exist!",
                                                               new Exception("Project is not exist!"));
        }
        // step2: send invite email
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("owner", owner.getDisplayName());
        param.put("projectName", project.getName());
        //begin get user
        User user = webService.getUser(member.getUserId());
        if(user==null){
            user= webService.getInactiveUser(member.getUserId());
        }
        //end
        String token = TokenGenerator.generate(user.getEmail() + member.getRoleId() + projectId + DateUtil.getNow());
        String queryString = "?userId=" + member.getUserId() + "&token=" + token;
        param.put("link", basePath + queryString);

        boolean result = sendMail(user.getEmail(), param,
                                  MailPropertiesUtil.getString("project.mail.inviteMember.title"),
                                  MailPropertiesUtil.getString("project.mail.inviteMember.template"));

        if (result) {
            // Step3:Insert invite history
            InvitationEntity invitation = new InvitationEntity();
            invitation.setId(UUIDUtil.getUUIDStr());
            invitation.setToken(token);
            invitation.setMemberId(member.getId());
            invitation.setAccount(member.getUserId());
            invitation.setCreateTime(DateUtil.getNow());
            invitation.setUpdateTime(invitation.getCreateTime());
            result = insertInvitation(invitation);
            ProjectMemberAttendees attendees = ProjectMemberAttendeesEntity.getDto(projectBiz.getAttendeeByUIDandPMID(member.getUserId(),member.getId()));
            //update attendee invitationId
            projectBiz.updateAttendeeInvitation(attendees.getId(),invitation.getId());
        }
        return result;
    }

    @Override
    public List<MemberView> showMembers(String projectId, String roleId, String ownerId) {
        List<ProjectMember> members = new ArrayList<ProjectMember>();
        // step1: list all members
        members = getMembers(projectId, roleId);
        //step1.1:get attendees：
        List<ProjectMember> projectMemberList = new ArrayList<ProjectMember>();
        for(ProjectMember member:members){
           List<ProjectMemberAttendees> attendeesList =projectBiz.getAttendees(member.getId());
           if(!attendeesList.isEmpty()){
               for(ProjectMemberAttendees entity : attendeesList){
                   ProjectMember mem = new ProjectMember();
                   mem.setId(entity.getId());
                   mem.setProjectId(member.getProjectId());
                   mem.setRoleId(member.getRoleId());
                   mem.setIsOrg(member.getIsOrg());
                   if(member.getIsOrg()==1){
                       mem.setGroupId(member.getMemberId());
                   }
                   mem.setUserId(entity.getUserId());
                   mem.setStatus(entity.getStatus());
                   mem.setEditable(entity.getEditable());
                   projectMemberList.add(mem);
               }
           }else{
               member.setGroupId(member.getMemberId());
               projectMemberList.add(member);
           }
           
        }
        List<ProjectMember> singleMember = new ArrayList<ProjectMember>();
        Map<Org, List<ProjectMember>> resultMap = new HashMap<Org, List<ProjectMember>>();
        // step2: check membertype=group,compare members with group in account
        Map<String, List<ProjectMember>> orgMember = new HashMap<String, List<ProjectMember>>();
        // Get users
        Set<String> ids = new HashSet<String>();
        for (ProjectMember member : projectMemberList) {
            if (member.getUserId() != null) {
                ids.add(member.getUserId());
            }
        }
        List<User> users = webService.getUserByIds(ids, false);
        Map<String, User> userMap = new HashMap<String, User>();
        for (User user : users) {
            if (user.getEmail() != null) {
                userMap.put(user.getId(), user);
            }
        }
        for (ProjectMember member : projectMemberList) {
            if (StringUtils.isEmpty(member.getGroupId())&&member.getIsOrg()!=1) {
                member.setMemberName(userMap.get(member.getUserId()).getDisplayName());
                singleMember.add(member);
            } else {
                if (orgMember.containsKey(member.getGroupId())) {
                    orgMember.get(member.getGroupId()).add(member);
                } else {
                    List<ProjectMember> memb = new ArrayList<ProjectMember>();
                    memb.add(member);
                    orgMember.put(member.getGroupId(), memb);
                }
            }
        }
        for (Map.Entry<String, List<ProjectMember>> entry : orgMember.entrySet()) {
            Org org = webService.getOrgById(entry.getKey(), ownerId,true);
            List<Member> orgMembers = new ArrayList<Member>();
            List<Member> exitsMembers = new ArrayList<Member>();
            getOrgMember(org, orgMembers);
           
            List<ProjectMember> mems = entry.getValue();
            List<ProjectMember> unExistMem = new ArrayList<ProjectMember>();
            List<ProjectMember> existMem = new ArrayList<ProjectMember>(); 
            
            if(org!=null&&orgMembers.isEmpty()){
                //if there are no members in this org in the project
                existMem.add(entry.getValue().get(0));
            }else{
                for (ProjectMember member : mems) {
                    // Get user id
                    User user = userMap.get(member.getUserId());
                    for(Member mem :orgMembers){
                        if (user!=null&&mem.getUserId().equals(user.getId())) {
//                            orgMembers.remove(mem);
                            exitsMembers.add(mem);
                            member.setMemberName(user.getDisplayName());
                            existMem.add(member);
                        } else {
                            unExistMem.add(member);
                        }
                    }
                    
                }
                //Get new member in org, these members are not invited
                orgMembers.removeAll(exitsMembers);
                // remove deleted member
                if (!unExistMem.isEmpty()) {
                    // mems.removeAll(unExistMem);
                    for (ProjectMember member : unExistMem) {
                        removeMember(member.getId(),false);
                    }
                }
                // add new member from org
                if (!orgMembers.isEmpty()) {
                    Set<String> idSet = new HashSet<String>();
                    for(Member member : orgMembers){
                        idSet.add(member.getUserId());
                    }
                    List<User> userList = webService.getUserByIds(idSet);
                    for (User user : userList) {
                        if (user.getEmail() != null) {
                            userMap.put(user.getId(), user);
                        }
                    }
                    for (Member member : orgMembers) {
                        ProjectMember mem = new ProjectMember();
                        User user = userMap.get(member.getUserId());
                        mem.setGroupId(mems.get(0).getGroupId());
                        mem.setMemberName(user.getDisplayName());
                        mem.setProjectId(mems.get(0).getProjectId());
                        mem.setRoleId(mems.get(0).getRoleId());
                        mem.setMemberType(mems.get(0).getMemberType());
                        mem.setStatus(-1);
                        mem.setUserId(user.getId());
                        existMem.add(mem);
                    }
                }
            }
           

            resultMap.put(org, existMem);
        }
        Org singleOrg = new Org();
        singleOrg.setId("Single");
        resultMap.put(singleOrg, singleMember);

        return convert2ViewObject(resultMap, ownerId,userMap);
    }
    private void getOrgMember(Org org, List<Member> members) {
        if(org!=null){
            if (org.getMembers() != null) {
                members.addAll(org.getMembers());
            }
            List<Org> subOrgs = org.getSubOrgs();
            if(subOrgs!=null){
                for (Org subOrg : subOrgs) {
                    getOrgMember(subOrg, members);
                }
            }
        }
        
    }

    private List<MemberView> convert2ViewObject(Map<Org, List<ProjectMember>> memberMap, String ownerId,Map<String,User> userMap) {
        // convert List to map
        Map<Org, Map<String, ProjectMember>> tempMap = new HashMap<Org, Map<String, ProjectMember>>();
        for (Map.Entry<Org, List<ProjectMember>> entry : memberMap.entrySet()) {
            Map<String, ProjectMember> pmMap = new HashMap<String, ProjectMember>();
            for (ProjectMember member : entry.getValue()) {
                pmMap.put(member.getUserId(), member);
            }
            tempMap.put(entry.getKey(), pmMap);

        }
        List<MemberView> members = new ArrayList<MemberView>();
        for (Map.Entry<Org, Map<String, ProjectMember>> entry : tempMap.entrySet()) {
            if ("Single".equals(entry.getKey().getId())) {
                for (Map.Entry<String, ProjectMember> subEntry : entry.getValue().entrySet()) {
                    MemberView member = new MemberView();
                    member.setId(subEntry.getValue().getId());
                    member.setName(subEntry.getValue().getMemberName());
                    member.setOrg(false);
                    member.setProjectId(subEntry.getValue().getProjectId());
                    member.setRoleId(subEntry.getValue().getRoleId());
                    //begin get user
                    User user = userMap.get(subEntry.getValue().getUserId());
                    //end
                    member.setAccount(user.getEmail());
                    //set user id
                    member.setUserId(user.getId());
                    member.setStatus(subEntry.getValue().getStatus());
                    member.setMemberCount(0);
                    member.setEditable(subEntry.getValue().getEditable()==0);
                    members.add(member);
                }
            } else {
                //begin get full org
                Org org = webService.getOrgPath(entry.getKey().getId(), ownerId);
                //end
                MemberView mem = new MemberView();
                mem = convert( org, entry.getKey(), tempMap, ownerId,userMap);
                members.add(mem);
            }
        }

        return members;
    }

    private MemberView convert(Org org, Org topOrg, Map<Org, Map<String, ProjectMember>> memberMap,
                         String ownerId,Map<String,User> userMap) {
        Integer memberCount = 0;
        Map<String, ProjectMember> pmMap = memberMap.get(topOrg);
        MemberView member = new MemberView();
        // get first member
        ProjectMember first = pmMap.entrySet().iterator().next().getValue();
        member.setId(org.getId());
        member.setName(org.getName());
        member.setOrg(true);
        member.setProjectId(first.getId());
        member.setRoleId(first.getRoleId());
        member.setStatus(first.getStatus());
        if (org.getId().equals(topOrg.getId())) {
            member.setNameNode(true);
            if(!StringUtil.isBlank(first.getMemberId())){
                member.setId(first.getMemberId());
            }
            //TODO
            org=topOrg;
        }
        List<MemberView> subMembers = new ArrayList<MemberView>();

        if (org.getMembers() != null && !org.getMembers().isEmpty()) {
            for (Member mem : org.getMembers()) {
                ProjectMember pm = pmMap.get(mem.getUserId());
                MemberView subMem = new MemberView();
                subMem.setId(pm.getId());
                subMem.setUserId(pm.getUserId());
                subMem.setName(pm.getMemberName());
                subMem.setOrg(false);
                subMem.setProjectId(pm.getProjectId());
                subMem.setRoleId(pm.getRoleId());
                //begin get user
                User usr= userMap.get(pm.getUserId());
                //end
                subMem.setAccount(usr.getEmail());
                subMem.setStatus(pm.getStatus());
                subMem.setMemberCount(0);
                subMem.setOrgId(pm.getGroupId());
                subMem.setEditable(pm.getEditable()==0);
                subMembers.add(subMem);
                memberCount++;
            }
        }
        if (org.getSubOrgs() != null && !org.getSubOrgs().isEmpty()) {
            for (Org subOrg : org.getSubOrgs()) {
                memberCount++;
                //begin get full org
                //TODO delete
//                Org orgSub = WebServiceUtil.getOrgPath(subOrg.getId(), ownerId);
                //end
                if(subOrg!=null&&subOrg.getId()!=null){
                    subMembers.add(convert(subOrg, topOrg, memberMap, ownerId,userMap)) ;
                }
                

            }
        }
        member.setMemberCount(memberCount);
        member.setMemberViews(subMembers);
        return member;
    }


    @Override
    public String savePrivilege(String userId, String fileId, String roleId, String[] privileges) {
        FileInfoEntity file = fileBiz.getFile(fileId);
        if(file == null || file.getProjectId() == null){
            throw PaasServerExceptionFactory.notFoundException("can not find Project File["+fileId+"]", null);
        }
        ProjectInfoEntity project = projectBiz.getProjectById(file.getProjectId());
        if(project == null){
            throw PaasServerExceptionFactory.notFoundException("can not find Project["+file.getProjectId()+"]", null);
        }
        ProjectResourceEntity resource = resourceBiz.getResourceByFileRole(fileId, roleId);
        Set<String> sPV = new HashSet<String>();
        for(String p : privileges){
            p = p.toLowerCase().trim();
            if(DocumentConstant.FILE_ENTER.equals(p)){
                sPV.add(DocumentConstant.FILE_ENTER);
            }
            else if(DocumentConstant.FILE_DELETE.equals(p)){
                sPV.add(DocumentConstant.FILE_DELETE);
            }
            else if(DocumentConstant.FILE_READ.equals(p)){
                sPV.add(DocumentConstant.FILE_READ);
            }
            else if(DocumentConstant.FILE_WRITE.equals(p)){
                sPV.add(DocumentConstant.FILE_WRITE);
            }
        }
        Date now = DateUtil.getNow();
        if (resource == null) {
            resource = new ProjectResourceEntity();
            resource.setId(UUIDUtil.getUUIDStr());
            resource.setFileId(fileId);
            resource.setRoleId(roleId);
            resource.setPrivileges(StringUtils.join(sPV,StringConst.SEPARATOR_COMMA));
            resource.setUpdateTime(now);
            resource.setUpdatorId(userId);
            List<FileInfoEntity> parents = fileBiz.getParents(file);
            // 子目录上设置权限时，父目录 需要自动设定 进入权限
            for(FileInfoEntity parent : parents){
                ProjectResourceEntity pv = resourceBiz.getResourceByFileRole(parent.getId(), roleId);
                if(pv != null){
                    String[] pvs = pv.getPrivileges().split(StringConst.SEPARATOR_COMMA);
                    if(Arrays.asList(pvs).contains(DocumentConstant.FILE_ENTER)){
                        break;
                    }
                    else{
                        if(StringUtils.isBlank(pv.getPrivileges())){
                            pv.setPrivileges(DocumentConstant.FILE_ENTER);
                        }
                        else{
                            pv.setPrivileges(pv.getPrivileges()+StringConst.SEPARATOR_COMMA+DocumentConstant.FILE_ENTER);
                        }
                        pv.setUpdateTime(now);
                        pv.setUpdatorId(userId);
                        resourceBiz.updateResource(pv);
                    }
                }
                else{
                    ProjectResourceEntity parentPV = new ProjectResourceEntity();
                    parentPV.setId(UUIDUtil.getUUIDStr());
                    parentPV.setFileId(parent.getId());
                    parentPV.setRoleId(roleId);
                    parentPV.setPrivileges(DocumentConstant.FILE_ENTER);
                    parentPV.setUpdateTime(now);
                    parentPV.setUpdatorId(userId);
                    resourceBiz.insertResource(parentPV);
                }
            }
            resourceBiz.insertResource(resource);
        } else {
            resource.setPrivileges(StringUtils.join(sPV,StringConst.SEPARATOR_COMMA));
            resource.setUpdateTime(now);
            resource.setUpdatorId(userId);
            // <=0 更新失败
            if (resourceBiz.updateResource(resource) <= 0) {
                return null;
            }
        }
        return resource.getId();
    }

    @Override
    public List<ProjectResource> getFileRolePrivilege(String userId, String fileId, String roleId) {
        FileInfoEntity file = fileBiz.getFile(fileId);
        if(file == null || file.getProjectId() == null){
            throw PaasServerExceptionFactory.notFoundException("can not find Project File["+fileId+"]", null);
        }
        ProjectInfoEntity project = projectBiz.getProjectById(file.getProjectId());
        if(project == null){
            throw PaasServerExceptionFactory.notFoundException("can not find Project["+file.getProjectId()+"]", null);
        }
        //TODO  需要检查 角色信息查询权限，目前检查根目录的读权限，只有管理员才有该权限
        privilege.checkReadPrivilege(userId, project.getFolderId(), false, false);
        if(StringUtils.isNotBlank(roleId)){
            List<ProjectResource> ret = new ArrayList<ProjectResource>();
            ProjectResourceEntity pre = resourceBiz.getResourceByFileRole(fileId, roleId);
            if(pre != null){
                ret.add(ProjectResourceEntity.getDto(pre));
            }
            return ret;
        }
        else{
            return resourceBiz.getFileRolePrivileges(null, fileId, true);
        }
    }

    /**
     * 将 给定的 权限格式，改成 继承格式
     * 
     * @param sPV
     * @return
     */
    private Set<String> selfPV2InheritPV(Set<String> sPV) {
        Set<String> iPV = new HashSet<String>();
        for (String pv : sPV) {
            // x 进入权限 不可继承
            if (DocumentConstant.FILE_ENTER.equals(pv.trim())) {
                continue;
            } else if (pv.trim().startsWith("i-")) {
                iPV.add(pv.trim());
            } else {
                iPV.add("i-" + pv.trim());
            }
        }
        return iPV;
    }

    @Override
    public List<Map<String, String>> showSuggestion(String userId) {
        List<Communicate> communicateList = webService.getContactList(userId);
        List<Org> orgs = webService.getInstitution(userId);
        List<Member> members = new ArrayList<Member>();
        getOrgMembers(orgs, members);
        Set<String> ids = new HashSet<String>();
        for (Communicate communicate : communicateList) {
            ids.add(communicate.getContactId());
        }
        for (Member member : members) {
            if (member.getUserId() != null) {
                ids.add(member.getUserId());
            }
        }
        // index map
        Map<String, Communicate> map = new HashMap<String, Communicate>();
        for (Communicate item : communicateList) {
            map.put(item.getContactId(), item);
        }

        // get all users
        List<User> users = webService.getUserByIds(ids, false);
        List<Map<String, String>> userlist = new ArrayList<Map<String, String>>();
        for (User item : users) {
            if (item != null) {
                Map<String, String> userInfo = new HashMap<String, String>();
                String tempProperty = null;
                // displayName
                if (map != null && map.get(item.getId()) != null) {
                    tempProperty = map.get(item.getId()).getRemarkName();
                }
                if (StringUtils.isNotBlank(tempProperty)) {
                    userInfo.put("displayName", tempProperty);
                } else {
                    userInfo.put("displayName", item.getDisplayName());
                }
                // accountName
                userInfo.put("accountName", item.getAccountName());
                //set userId 
                userInfo.put("accountId", item.getId());
                userlist.add(userInfo);
            }
        }
        Collections.sort(userlist, new Comparator<Map<String, String>>() {

            @Override
            public int compare(Map<String, String> o1, Map<String, String> o2) {
                if (o1.get("accountName").toCharArray()[0] > o2.get("accountName").toCharArray()[0]) {
                    return 1;
                } else if (o1.get("accountName").toCharArray()[0] < o2.get("accountName").toCharArray()[0]) {
                    return -1;
                }
                return 0;
            }
        });
        return userlist;
    }

    private void getOrgMembers(List<Org> orgs, List<Member> members) {
        for (Org org : orgs) {
            if (org != null) {
                if (org.getMembers() != null && !org.getMembers().isEmpty()) {
                    members.addAll(org.getMembers());
                }
                if (org.getSubOrgs() != null && !org.getSubOrgs().isEmpty()) {
                    getOrgMembers(org.getSubOrgs(), members);
                }
            }
        }

    }

    @Override
    public List<MemberView> getOrg(String userId, String projectId, String roleId) {
        List<Org> orgs = webService.getInstitution(userId);
        List<MemberView> resultList = new ArrayList<MemberView>();
        convertOrg2MemberView(orgs, resultList, false);
        //Get Org added.
        List<ProjectMemberEntity> orgList= projectBiz.getAddedOrgs(projectId,roleId);
        Map<String,Integer> statusMap =new HashMap<String,Integer>();
        for(ProjectMemberEntity entity : orgList){
            if(entity!=null){
                statusMap.put(entity.getGroupId(), 0);
            }
            
        }
        setMemberStatus(resultList,statusMap,projectId,roleId);
        return resultList;
    }
    private void setMemberStatus(List<MemberView> memberList,Map<String,Integer> statusMap,String projectId,String roleId){
        for(MemberView member: memberList){
            member.setProjectId(projectId);
            member.setRoleId(roleId);
            if(member.isOrg()){
                member.setStatus(statusMap.get(member.getId())==null?-1:statusMap.get(member.getId()));
            }
            if(member.getMemberViews()!=null&&!member.getMemberViews().isEmpty()){
                setMemberStatus(member.getMemberViews(),statusMap,projectId,roleId);
            }
        }
    }
    private void convertOrg2MemberView(List<Org> orgs, List<MemberView> resultList, boolean needMembers) {
        for (Org org : orgs) {
            MemberView member = new MemberView();
            member.setId(org.getId());
            member.setName(org.getName());
            member.setOrg(true);
            //Set uerid = orgId,if member is org
            member.setUserId(org.getId());
            member.setEditable(true);
            int count =0;
            List<MemberView> subResultList = new ArrayList<MemberView>();
            if (needMembers && org.getMembers() != null && !org.getMembers().isEmpty()) {
                count=count+org.getMembers().size();
                for (Member subMem : org.getMembers()) {
                    MemberView subMember = new MemberView();
                    subMember.setAccount(subMem.getEmail());
                    subMember.setId(subMem.getUserId());
                    subMember.setName(subMem.getName());
                    subMember.setOrg(false);
                    subMember.setUserId(subMem.getUserId());
                    subMember.setEditable(true);
                    subResultList.add(subMember);
                }

            }
            if (org.getSubOrgs() != null && !org.getSubOrgs().isEmpty()) {
                count=count+org.getSubOrgs().size();
                convertOrg2MemberView(org.getSubOrgs(), subResultList, needMembers);
            }
            member.setMemberCount(count);
            member.setMemberViews(subResultList);
            resultList.add(member);
        }
    }
    private MemberView convertOrgWithNameNode(Org fullOrg,Org sourceOrg,Map<String, ProjectMemberEntity> statusMap ,List<MemberView> resultList){

        MemberView member = new MemberView();
        member.setId(fullOrg.getId());
        member.setName(fullOrg.getName());
        member.setOrg(true);
        //Set uerid = orgId,if member is org
        member.setUserId(fullOrg.getId());
        member.setEditable(true);
        if(fullOrg.getId().equals(sourceOrg.getId())){
            member.setNameNode(true); 
            fullOrg = sourceOrg;
        }
        int count =0;
        List<MemberView> subResultList = new ArrayList<MemberView>();
        if (fullOrg.getMembers() != null && !fullOrg.getMembers().isEmpty()) {
            count=count+fullOrg.getMembers().size();
            for (Member subMem : fullOrg.getMembers()) {
                MemberView subMember = new MemberView();
                subMember.setAccount(subMem.getEmail());
                subMember.setId(subMem.getUserId());
                subMember.setName(subMem.getName());
                subMember.setOrg(false);
                subMember.setUserId(subMem.getUserId());
                subMember.setStatus(statusMap.get(subMem.getUserId()).getStatus());
                subMember.setEditable(true);
                subResultList.add(subMember);
            }

        }
        
        if (fullOrg.getSubOrgs() != null && !fullOrg.getSubOrgs().isEmpty()) {
            count=count+fullOrg.getSubOrgs().size();
            for(Org subOrg :fullOrg.getSubOrgs()){
                convertOrgWithNameNode(subOrg,sourceOrg,statusMap,subResultList);
            }
            
        }
        member.setMemberCount(count);
        member.setMemberViews(subResultList);
        resultList.add(member);
    
        return null;
    }
    @Override
    public List<MemberView> showProjectMembers(String projectId, String ownerId) {
        List<ProjectMember> members = new ArrayList<ProjectMember>();
        // step1: list all members
        members = getMembers(projectId, null);
        // convert project member to memberview
        List<MemberView> resultList = new ArrayList<MemberView>();
        //set user id 
        Set<String> ids = new HashSet<String>();
        for (ProjectMember projectMember : members) {
            MemberView member = new MemberView();
            member.setId(projectMember.getUserId());
            ids.add(projectMember.getUserId());
           
            member.setProjectId(projectMember.getProjectId());
            member.setRoleId(projectMember.getRoleId());
           
            resultList.add(member);
        }
        //Get user list
        List<User> users = webService.getUserByIds(ids);
        Map<String,User> userMap = new HashMap<String,User>();
        for(User user : users){
            userMap.put(user.getId(), user);
        }
        for(MemberView mem: resultList){
            if (userMap.get(mem.getId())!= null) {
                mem.setName(userMap.get(mem.getId()).getDisplayName());
            }
            mem.setAccount(userMap.get(mem.getId()).getEmail());
        }
        return resultList;
    }

//    @Override
//    public File getProjectFolder(String userId, String projectId) {
//        //检查项目跟目录权限
//        ProjectInfoEntity project =  projectBiz.getProjectById(projectId);
//        if(project == null){
//            throw PaasServerExceptionFactory.notFoundException("can not find Project["+projectId+"]", null);
//        }
//        Set<String> pPV = resourceBiz.getFilePrivileges(userId, project.getFolderId(), false);
//        File file = FileInfoEntity.getDto(fileBiz.getFileWithFolderCount(project.getFolderId()), false);
//        file.getAttributes().put(DocumentConstant.FILE_PRIVILEGES, pPV.toArray());
//        file.setDescription(project.getDescription());
//        // 只有进入权限时，内部文件信息，需要检查权限
//        if(pPV.size()==1 && pPV.contains(DocumentConstant.FILE_ENTER)){
//            List<File> files = this.getFiles(userId, file.getId(), null, null, false);
//            int folderCount = 0;
//            for(File f : files){
//                if(f.isFolder()){
//                    folderCount++;
//                }
//            }
//            file.setFolderCount(folderCount);
//            file.setCount(files.size());
//        }
//        return file;
//    }

    @Override
    public boolean updateInvitationStatus(String email, String token) {
        return projectBiz.updateInvitationStatus(email,token);
    }

    @Override
    public ProjectMemberAttendees getAttendeeById(String id) {
        return ProjectMemberAttendeesEntity.getDto(projectBiz.getAttendeeById(id));
    }

    @Override
    public ProjectMember getMember(String projectId, String roleId, String memberId) {
        return ProjectMemberEntity.getDto(projectBiz.getMember(projectId, roleId, memberId, null));
    }

    @Override
    public boolean setInvitaionInvalid(String id) {
        return projectBiz.setInvitaionInvalid(id);
    }
    public void setProjectBiz(ProjectBiz projectBiz) {
        this.projectBiz = projectBiz;
    }
    public void setResourceBiz(ProjectResourceBiz resourceBiz) {
        this.resourceBiz = resourceBiz;
    }
    public void setFileBiz(FileBiz fileBiz) {
        this.fileBiz = fileBiz;
    }
    public void setPrivilege(DocumentPrivilege privilege) {
        this.privilege = privilege;
    }
    public void setWebService(WebService webService) {
        this.webService = webService;
    }
}
